package org.xxpay.pay.channel.yunhaofu;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Component;
import org.xxpay.common.util.Util;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;
import org.xxpay.pay.channel.shengfutong.SftpayConfig;

import java.util.*;

@Component
public class YunhaofuNotifyService extends BasePayNotify {

    private final static String logPrefix = "【云好付】";

    @Override
    public String getChannelName() {
        return YunhaofupayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {
        JSONObject bizContext = getRequestParameters(notifyData);

        _log.info("{}回调请求响应参数：{}", logPrefix, bizContext.toJSONString());

        JSONObject retObj = buildFailRetObj();
        try {
            if (!verifyPayParams(bizContext)) {
                retObj.put(PayConstant.RESPONSE_RESULT, SftpayConfig.RESPONSE_RESULT_FAIL);
                return retObj;
            }
            PayOrder payOrder = (PayOrder) bizContext.get("payOrder");
            byte payStatus = payOrder.getStatus(); // 0：订单生成，1：支付中，-1：支付失败，2：支付成功，3：业务处理完成，-2：订单过期
            if (payStatus != PayConstant.PAY_STATUS_SUCCESS && payStatus != PayConstant.PAY_STATUS_COMPLETE) {
                int updatePayOrderRows = rpcCommonService.rpcPayOrderService.updateStatus4Success(payOrder.getPayOrderId());
                if (updatePayOrderRows != 1) {
                    _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
                    retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
                    return retObj;
                }
                _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
                payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
            }
            // 业务系统后端通知
            baseNotify4MchPay.doNotify(payOrder, true);
            _log.info("====== 完成处理vippay支付回调通知 ======");
            retObj.put(PayConstant.RESPONSE_RESULT, "success");
        } catch (Exception e) {
            _log.error(e, logPrefix + "处理异常");
        }
        return retObj;
    }

    public boolean verifyPayParams(JSONObject payContext) {
        // 查询payOrder记录
        String payOrderId = payContext.getString("order_no");
        PayOrder payOrder = rpcCommonService.rpcPayOrderService.findByPayOrderId(payOrderId);
        if (payOrder == null) {
            _log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
            payContext.put("retMsg", "Can't found payOrder");
            return false;
        }
        if(!payContext.getString("pay_status").equals("10000")){
            _log.error("订单{}交易失败，回调内容", payOrderId,payContext.toJSONString());
            payContext.put("retMsg", "订单{}交易失败");
            return false;
        }
        YunhaofupayConfig yunhaofupayConfig = new YunhaofupayConfig(getPayParam(payOrder));

        Map<String, String> reqPrameters = Maps.newHashMap();
        reqPrameters.put("code", payContext.getString("code"));
        reqPrameters.put("msg", payContext.getString("msg"));
        reqPrameters.put("order_no", payContext.getString("order_no"));
        reqPrameters.put("money", payContext.getString("money"));
        reqPrameters.put("platform_ord er_no", payContext.getString("platform_ord er_no"));

        String signTxt = getSignToken(reqPrameters);

        _log.info("{}通道回调签名前字符串{}", logPrefix, signTxt+yunhaofupayConfig.getPrivateKey());

        String signValue = SignUtils.MD5.createSign(signTxt, yunhaofupayConfig.getPrivateKey(), SignUtils.CHARSET_UTF8);

        if(!payContext.getString("sign").equals(signValue)) {
            _log.error("验证签名失败. payOrderId={}, ", payOrderId);
            payContext.put("retMsg", "验证签名失败");
            return false;
        }

        // 核对金额
        long outPayAmt = Util.conversionCentAmount(payContext.getBigDecimal("money"));
        long dbPayAmt = payOrder.getAmount().longValue();
        if (dbPayAmt != outPayAmt) {
            _log.error("金额不一致. outPayAmt={},transOrderId={}", outPayAmt, payOrderId);
            payContext.put("retMsg", "金额不一致");
            return false;
        }
        payContext.put("payOrder", payOrder);
        return true;
    }

    /**
     * 生成签名
     * @param map
     * @return
     */
    public String getSignToken(Map<String, String> map) {
        String result = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(val);
                    }
                }
            }
            result = sb.toString();
        } catch (Exception e) {
            return null;
        }
        return result;
    }
}
